/* 
 * Licensed Materials - Property of IBM
 * (c) Copyright IBM Corporation 2010. All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:  Use,
 * duplication or disclosure restricted by GSA ADP Schedule
 * Contract with IBM Corp.
 *
 * This code is released under the terms of the Eclipse Public License
 * version 1.0 which can be found at the top level of this project or
 * or at http://www.eclipse.org/org/documents/epl-v10.php
 */

package com.ibm.mining.model;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ibm.mining.AssertionException;
import com.ibm.mining.MyAssert;

public class Type {
	
	String name;
	Integer length;
	Type listItemType;
	boolean primitive;
	Model model;
	
	private static Pattern listPattern = Pattern.compile("^List<([\\p{Alnum}_]+)>$");
	
	void test(String[] strings) {
		List<String> f = Arrays.asList(strings);
		
	}
	
	Type(String name, Integer length, Model model) {
		this.name = name;
		this.model = model;
		this.length = length;
		Matcher m = Type.listPattern.matcher(name);
		if (m.matches()) {
			listItemType = model.getType(m.group(1));
		}
	}
	
	Type(String name, Model model) {
		this(name, null, model);
	}

	public ModelClass getModelClassForType() {
		MyAssert.check(!isPrimitiveType(), "Can't get Model Class for primitive type" + name);
		MyAssert.check(!isListItemType(), "Can't get Model Class for a list type" + name);
		return model.getModelClass(getName());
	}
	
	public Type getListItemType() {
		return listItemType;
	}
	
	public boolean isListItemType() {
		return listItemType != null;
	}
	
	public boolean isPrimitiveType() {
		return primitive;
	}
	
	public boolean isModelClassType() {
		return listItemType == null && !primitive;
	}
	
	/* this is true if it is a model class type *or*
	 * is a list of something that is a model class type (recursively)
	 */
	public boolean hasBaseModelClassType() {
		if (isListItemType()) {
			return getListItemType().hasBaseModelClassType();
		} else {
			return isModelClassType();
		}
	}
	
	public ModelClass getBaseModelClassForType() {
		if (isModelClassType()) {
			return getModelClassForType();
		}
		if (isListItemType()) {
			return getListItemType().getBaseModelClassForType();
		} 
		throw new RuntimeException("Can't get the base model class for type " + toString());
	}
	
	public String getName() {
		return name;
	}
	
	public boolean hasLength() {
		return length != null;
	}
	
	public int getLength() {
		return length;
	}
	
	public String toString() {
		String s = "<Type : ";
		if (isListItemType()) {
			s += "List of " + listItemType.toString();
		} else {
			s += getName();
		}
		s += ">";
		return s;
	}
	
	public static void main(String args[]) {
		
		JazzMiningModel m = new JazzMiningModel();
		
		m.buildModelClass("FooBar");
		Type t = m.buildType("FooBar");
		
		System.out.println("Made type " + t);
		t = m.getType("String");
		System.out.println("Made type " + t);
		
		t = m.buildType("List<FooBar>");
		System.out.println("Made type " + t);
		
		t.getListItemType().getModelClassForType().output(System.out);
		
		/* this should cause an exception */
		try {
			t = m.buildType("List<bar>");
		} catch (AssertionException e) {
			System.out.println("Caught : " + e);
		}

		m.buildModel();
		m.output(System.out);
	}
}
